import os
import json
import logging
import requests
from typing import Dict, Any
from datetime import datetime
from django.conf import settings
from langchain.llms.base import LLM
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.schema import HumanMessage

logger = logging.getLogger(__name__)

class AuditChain:
    """评论审核链 - AI完全自主决策（使用阿里云DashScope qwen-max模型 + 百度图片审核）"""
    
    def __init__(self):
        self.config = settings.LANGCHAIN_CONFIG
        self.baidu_config = settings.BAIDU_AUDIT_CONFIG
        
        # 初始化阿里云DashScope qwen-max模型
        self.llm = self._init_dashscope_qwen()
        
        # 初始化百度API token
        self.baidu_token = self._get_baidu_token()
        
        # 审核提示模板
        self.audit_prompt = PromptTemplate(
            input_variables=["text"],
            template="""
请对以下评论内容进行AI自主审核，判断是否包含敏感内容。

评论内容：{text}

请严格按照以下JSON格式返回审核结果：
{{
    "is_sensitive": true/false,
    "sensitive_words": ["敏感词1", "敏感词2"],
    "reason": "审核原因说明",
    "suggestion": "改进建议",
    "confidence": 95,
    "audit_decision": "pass/reject"
}}

审核标准：
1. 包含侮辱性、攻击性语言
2. 包含政治敏感内容
3. 包含色情、暴力内容
4. 包含商业机密或个人信息
5. 包含垃圾信息或广告

请确保返回的是有效的JSON格式。
"""
        )
        
    def _init_dashscope_qwen(self) -> ChatOpenAI:
        """初始化阿里云DashScope qwen-max模型"""
        try:
            llm = ChatOpenAI(
                model=self.config['model_name'],
                api_key=self.config['api_key'],
                base_url=self.config['base_url'],
                temperature=0.1,
                max_tokens=self.config['max_length'],
                timeout=self.config['timeout']
            )
            logger.info("阿里云DashScope qwen-max模型初始化成功")
            return llm
        except Exception as e:
            logger.error(f"阿里云DashScope模型初始化失败: {e}")
            return None
    
    def _get_baidu_token(self) -> str:
        """获取百度API访问令牌"""
        try:
            if self.baidu_config['access_token']:
                return self.baidu_config['access_token']
            
            url = "https://aip.baidubce.com/oauth/2.0/token"
            params = {
                'grant_type': 'client_credentials',
                'client_id': self.baidu_config['api_key'],
                'client_secret': self.baidu_config['secret_key']
            }
            
            response = requests.post(url, params=params)
            if response.status_code == 200:
                token = response.json().get('access_token')
                logger.info("百度API token获取成功")
                return token
            else:
                logger.error(f"百度API token获取失败: {response.text}")
                return ""
        except Exception as e:
            logger.error(f"获取百度API token失败: {e}")
            return ""
    
    def audit_with_dashscope_qwen(self, text: str) -> Dict[str, Any]:
        """使用阿里云DashScope qwen-max模型审核文本"""
        try:
            if not self.llm:
                logger.error("阿里云DashScope模型未初始化")
                return {
                    'is_sensitive': False,
                    'sensitive_words': [],
                    'reason': '模型未初始化',
                    'suggestion': '请检查模型配置',
                    'confidence': 0,
                    'audit_decision': 'pass',
                    'method': 'dashscope_qwen'
                }
            
            # 构建提示
            prompt = self.audit_prompt.format(text=text)
            
            # 调用模型
            response = self.llm([HumanMessage(content=prompt)])
            result_text = response.content
            
            # 智能解析结果
            try:
                # 尝试直接解析JSON
                result = json.loads(result_text)
                result['method'] = 'dashscope_qwen'
                logger.info(f"DashScope审核完成: {result['audit_decision']}")
                return result
            except json.JSONDecodeError:
                # 如果JSON解析失败，尝试智能解析文本
                logger.warning(f"DashScope返回结果不是标准JSON，尝试智能解析: {result_text}")
                
                # 智能解析逻辑
                result = self._parse_dashscope_response(result_text)
                result['method'] = 'dashscope_qwen'
                logger.info(f"DashScope智能解析完成: {result['audit_decision']}")
                return result
                
        except Exception as e:
            logger.error(f"DashScope审核失败: {e}")
            return {
                'is_sensitive': False,
                'sensitive_words': [],
                'reason': f'审核失败: {str(e)}',
                'suggestion': '请检查网络连接',
                'confidence': 0,
                'audit_decision': 'pass',
                'method': 'dashscope_qwen'
            }
    
    def _parse_dashscope_response(self, response_text: str) -> Dict[str, Any]:
        """智能解析DashScope模型返回的文本结果"""
        try:
            response_text = response_text.strip().lower()
            
            # 判断是否包含敏感内容
            sensitive_indicators = [
                '敏感', '违规', '不当', '禁止', '拒绝', '不通过', 'fail', 'reject', 'deny',
                '暴力', '色情', '政治', '宗教', '歧视', '仇恨', '侮辱', '谩骂', '脏话',
                '傻逼', '草泥马', '鸡巴', '约炮', '性', '黄', '毒', '赌'
            ]
            
            # 判断是否通过
            pass_indicators = [
                '通过', '正常', '合适', '可以', '允许', 'pass', 'approve', 'accept',
                '积极', '正面', '好评', '满意', '推荐', '不错', '很好', '优秀'
            ]
            
            # 检测敏感词
            detected_words = []
            for word in sensitive_indicators:
                if word in response_text:
                    detected_words.append(word)
            
            # 判断审核结果
            is_sensitive = len(detected_words) > 0
            
            # 如果检测到敏感词，直接拒绝
            if is_sensitive:
                return {
                    'is_sensitive': True,
                    'sensitive_words': detected_words,
                    'reason': f'检测到敏感内容: {", ".join(detected_words)}',
                    'suggestion': '请修改评论内容',
                    'confidence': 0.8,
                    'audit_decision': 'reject'
                }
            
            # 检查是否明确通过
            has_pass_indicator = any(indicator in response_text for indicator in pass_indicators)
            
            if has_pass_indicator:
                return {
                    'is_sensitive': False,
                    'sensitive_words': [],
                    'reason': '内容审核通过',
                    'suggestion': '评论可以发布',
                    'confidence': 0.7,
                    'audit_decision': 'pass'
                }
            
            # 默认通过（保守策略）
            return {
                'is_sensitive': False,
                'sensitive_words': [],
                'reason': '内容无明显违规',
                'suggestion': '评论可以发布',
                'confidence': 0.5,
                'audit_decision': 'pass'
            }
            
        except Exception as e:
            logger.error(f"智能解析失败: {e}")
            # 解析失败时，保守地通过
            return {
                'is_sensitive': False,
                'sensitive_words': [],
                'reason': '解析失败，默认通过',
                'suggestion': '请重试',
                'confidence': 0.3,
                'audit_decision': 'pass'
            }
    
    def audit_text_with_baidu(self, text: str) -> Dict[str, Any]:
        """使用百度API进行文本审核"""
        try:
            if not self.baidu_token:
                logger.error("百度API token未获取")
                return {
                    'is_sensitive': False,
                    'sensitive_words': [],
                    'reason': '百度API未配置',
                    'suggestion': '请配置百度API',
                    'confidence': 0,
                    'audit_decision': 'pass',
                    'method': 'baidu_text'
                }
            
            url = self.baidu_config['text_audit_url']
            params = {'access_token': self.baidu_token}
            data = {'text': text}
            
            response = requests.post(url, params=params, data=data)
            if response.status_code == 200:
                result = response.json()
                return self._parse_baidu_text_result(result)
            else:
                logger.error(f"百度文本审核失败: {response.text}")
                return {
                    'is_sensitive': False,
                    'sensitive_words': [],
                    'reason': '百度API调用失败',
                    'suggestion': '请检查API配置',
                    'confidence': 0,
                    'audit_decision': 'pass',
                    'method': 'baidu_text'
                }
        except Exception as e:
            logger.error(f"百度文本审核异常: {e}")
            return {
                'is_sensitive': False,
                'sensitive_words': [],
                'reason': f'审核异常: {str(e)}',
                'suggestion': '请重试',
                'confidence': 0,
                'audit_decision': 'pass',
                'method': 'baidu_text'
            }
    
    def _parse_baidu_text_result(self, baidu_result: Dict) -> Dict[str, Any]:
        """解析百度文本审核结果"""
        try:
            conclusion = baidu_result.get('conclusion', '')
            conclusion_type = baidu_result.get('conclusionType', 1)
            
            # 百度审核结果：1-合规，2-不确定，3-不合规，4-审核失败
            is_sensitive = conclusion_type in [2, 3]
            audit_decision = 'pass' if conclusion_type == 1 else 'reject'
            
            # 提取敏感词
            sensitive_words = []
            if 'data' in baidu_result:
                for item in baidu_result['data']:
                    if 'hits' in item:
                        for hit in item['hits']:
                            sensitive_words.append(hit.get('word', ''))
            
            return {
                'is_sensitive': is_sensitive,
                'sensitive_words': sensitive_words,
                'reason': conclusion,
                'suggestion': '请修改敏感内容',
                'confidence': 90 if conclusion_type != 4 else 0,
                'audit_decision': audit_decision,
                'method': 'baidu_text'
            }
        except Exception as e:
            logger.error(f"解析百度文本审核结果失败: {e}")
            return {
                'is_sensitive': False,
                'sensitive_words': [],
                'reason': '结果解析失败',
                'suggestion': '请重试',
                'confidence': 0,
                'audit_decision': 'pass',
                'method': 'baidu_text'
            }
    
    def audit_image_with_baidu(self, image_url: str) -> Dict[str, Any]:
        """使用百度API进行图片审核（从URL下载图片）"""
        try:
            if not self.baidu_token:
                logger.error("百度API token未获取")
                return {
                    'is_sensitive': False,
                    'sensitive_words': [],
                    'reason': '百度API未配置',
                    'suggestion': '请配置百度API',
                    'confidence': 0,
                    'audit_decision': 'pass',
                    'method': 'baidu_image'
                }
            
            # 下载图片
            response = requests.get(image_url, timeout=10)
            if response.status_code != 200:
                logger.error(f"图片下载失败: {image_url}")
                return {
                    'is_sensitive': False,
                    'sensitive_words': [],
                    'reason': '图片下载失败',
                    'suggestion': '请检查图片URL',
                    'confidence': 0,
                    'audit_decision': 'pass',
                    'method': 'baidu_image'
                }
            
            # 转换为base64
            import base64
            image_base64 = base64.b64encode(response.content).decode('utf-8')
            
            url = self.baidu_config['image_audit_url']
            params = {'access_token': self.baidu_token}
            data = {'image': image_base64}
            
            response = requests.post(url, params=params, data=data)
            if response.status_code == 200:
                result = response.json()
                return self._parse_baidu_image_result(result)
            else:
                logger.error(f"百度图片审核失败: {response.text}")
                return {
                    'is_sensitive': False,
                    'sensitive_words': [],
                    'reason': '百度API调用失败',
                    'suggestion': '请检查API配置',
                    'confidence': 0,
                    'audit_decision': 'pass',
                    'method': 'baidu_image'
                }
        except Exception as e:
            logger.error(f"百度图片审核异常: {e}")
            return {
                'is_sensitive': False,
                'sensitive_words': [],
                'reason': f'审核异常: {str(e)}',
                'suggestion': '请重试',
                'confidence': 0,
                'audit_decision': 'pass',
                'method': 'baidu_image'
            }
    
    def _parse_baidu_image_result(self, baidu_result: Dict) -> Dict[str, Any]:
        """解析百度图片审核结果"""
        try:
            conclusion = baidu_result.get('conclusion', '')
            conclusion_type = baidu_result.get('conclusionType', 1)
            
            # 百度审核结果：1-合规，2-不确定，3-不合规，4-审核失败
            is_sensitive = conclusion_type in [2, 3]
            audit_decision = 'pass' if conclusion_type == 1 else 'reject'
            
            # 提取违规类型
            violation_type = []
            if 'data' in baidu_result:
                for item in baidu_result['data']:
                    if 'type' in item:
                        violation_type.append(item['type'])
            
            return {
                'is_sensitive': is_sensitive,
                'violation_type': violation_type,
                'reason': conclusion,
                'suggestion': '请修改图片内容',
                'confidence': 90 if conclusion_type != 4 else 0,
                'audit_decision': audit_decision,
                'method': 'baidu_image'
            }
        except Exception as e:
            logger.error(f"解析百度图片审核结果失败: {e}")
            return {
                'is_sensitive': False,
                'violation_type': [],
                'reason': '结果解析失败',
                'suggestion': '请重试',
                'confidence': 0,
                'audit_decision': 'pass',
                'method': 'baidu_image'
            }
    
    def audit_text(self, text: str) -> Dict[str, Any]:
        """审核文本内容（优先使用DashScope，备选百度API）"""
        if not text or not text.strip():
            return {
                'is_sensitive': False,
                'sensitive_words': [],
                'reason': '文本为空',
                'suggestion': '请输入评论内容',
                'confidence': 100,
                'audit_decision': 'pass',
                'method': 'empty_text'
            }
        
        # 优先使用DashScope qwen-max模型
        result = self.audit_with_dashscope_qwen(text)
        if result and result.get('audit_decision') in ['pass', 'reject']:
            return result
        
        # 备选百度API
        logger.warning("DashScope审核失败，使用百度API备选")
        return self.audit_text_with_baidu(text)
    
    def audit_image(self, image_url: str) -> Dict[str, Any]:
        """使用百度API审核图片内容（从七牛云URL）"""
        return self.audit_image_with_baidu(image_url)
    
    def add_audit_task(self, comment_id: str, text: str, image_url: str = None):
        """添加审核任务到Redis队列"""
        try:
            from django.core.cache import cache
            import json
            
            task_data = {
                'comment_id': comment_id,
                'text': text,
                'image_url': image_url,
                'create_time': datetime.now().isoformat()
            }
            
            # 添加到Redis队列
            cache_key = f"audit_task:{comment_id}"
            cache.set(cache_key, json.dumps(task_data), timeout=3600)
            
            logger.info(f"审核任务已添加到队列: {comment_id}")
            return True
        except Exception as e:
            logger.error(f"添加审核任务失败: {e}")
            return False
    
    def get_audit_result(self, comment_id: str) -> Dict[str, Any]:
        """获取审核结果"""
        try:
            from django.core.cache import cache
            import json
            
            # 从Redis获取审核结果
            result_key = f"audit_result:{comment_id}"
            result_data = cache.get(result_key)
            
            if result_data:
                return json.loads(result_data)
            else:
                return None
                
        except Exception as e:
            logger.error(f"获取审核结果失败: {e}")
            return None

# 创建全局审核链实例
audit_chain = AuditChain() 